﻿using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Asplode.InputHandler
{
    public class InputManager
    {
        private Dictionary<string, InputAction> actionMappings;

        public InputAction this[string identifier]
        {
            get
            {
                if (!actionMappings.ContainsKey(identifier))
                {
                    // Create an empty action and return it for editing if none exists
                    InputAction temp = new InputAction(identifier, false, false, false, false);
                    this.AddAction(temp);
                }
                return actionMappings[identifier];
            }
        }

        public InputManager()
        {
            actionMappings = new Dictionary<string, InputAction>();
        }

        #region Add/Remove Action
        public void AddAction(InputAction action)
        {
            if (!actionMappings.ContainsKey(action.Identifier))
            {
                actionMappings.Add(action.Identifier, action);
            }
        }

        public void RemoveAction(InputAction action)
        {
            if (actionMappings.ContainsKey(action.Identifier))
            {
                actionMappings.Remove(action.Identifier);
            }
        }

        public void RemoveAction(string identifier)
        {
            if (actionMappings.ContainsKey(identifier))
            {
                InputAction action = actionMappings[identifier];
                actionMappings.Remove(identifier);
            }
        }
        #endregion

        public void Update(GameTime gameTime)
        {
            KeyboardState ksState = Keyboard.GetState();

            MouseState mState = Mouse.GetState();

            foreach (InputAction action in actionMappings.Values)
            {
                action.UpdateKeyboard(ksState, gameTime);

                action.UpdateMouse(mState, gameTime);
            }
        }

        #region Key Assignment Save/Load 

        public bool LoadActionsFromXml(string pathToXml)
        {
            if (File.Exists(pathToXml))
            {
                using (FileStream fs = new FileStream(pathToXml, FileMode.Open, FileAccess.Read))
                {
                    XmlSerializer ser = new XmlSerializer(typeof(List<InputAction>));
                    List<InputAction> newActions = (List<InputAction>)ser.Deserialize(fs);

                    fs.Close();

                    for (int i = 0; i < newActions.Count; i++)
                    {
                        this.AddAction(newActions[i]);
                    }
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        public void SaveActionsToXml(string pathToXml)
        {
            List<InputAction> actions = new List<InputAction>();
            foreach (InputAction action in actionMappings.Values)
            {
                actions.Add(action);
            }

            using (FileStream fs = new FileStream(pathToXml, FileMode.Create, FileAccess.Write))
            {
                XmlSerializer ser = new XmlSerializer(typeof(List<InputAction>));
                ser.Serialize(fs, actions);

                fs.Flush();
                fs.Close();
            }
        }
        #endregion
    }
}
